/**
 * Extended Cookie
 * extCookie/idsCookie/objCookie (see below)
 *
 * Copyright (c) 2009 David Berlioz <berlioz@nicematin.fr>
 * Licensed under GPL licenses:
 * http://www.gnu.org/licenses/gpl.html
 */

/**
 * extCookie : simple read/write cookie object
 * 
 * usage :
 * var myBasicCookie = new extCookie('cookie1'); -- create/read the cookie
 * myBasicCookie.setValue('foo'); -- set new value
 * myBasicCookie.write(); -- store the value
 * val = myBasicCookie.getValue(); -- get the value
 */
extCookie = function(name, expires, path, domain, secure)
{
	this._name=name;
	this._expires=expires;
	this._path=path;
	this._domain=domain;
	this._secure=secure;
	this._value=null;
	this.read();
}

extCookie.prototype.setValue = function(value)
{
	this._value=value;
}
extCookie.prototype.getValue = function()
{
	return this._value;
}

extCookie.prototype.rawRead = function()
{
  var dc = document.cookie;
  var prefix = this._name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return this._value=null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return this._value=unescape(dc.substring(begin + prefix.length, end));
}
extCookie.prototype.read = function()
{
	return this.rawRead();
}

extCookie.prototype.rawWrite = function()
{
  var curCookie = this._name + "=" + escape(this._value) +
      ((this._expires) ? "; expires=" + this._expires.toGMTString() : "") +
      ((this._path) ? "; path=" + this._path : "") +
      ((this._domain) ? "; domain=" + this._domain : "") +
      ((this._secure) ? "; secure" : "");
  document.cookie = curCookie;
}
extCookie.prototype.write = function()
{
	this.rawWrite();
}

extCookie.prototype.rawDelete = function()
{
    document.cookie = this._name + "=" +
    ((this._path) ? "; path=" + this._path : "") +
    ((this._domain) ? "; domain=" + this._domain : "") +
    "; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
extCookie.prototype.del = function()
{
	this.rawDelete();
}


/**
 * idsCookie : fifo array of IDs (int) cookie
 * try to store hundreds of IDs in one cookie.
 * 
 * usage :
 * var myArrayCookie = new idsCookie('cookie2'); -- create/read the cookie
 * myArrayCookie.addId(123); -- add new ID
 * myArrayCookie.write(); -- store the cookie
 * if(myBasicCookie.isId(123)) {-- STUFF --}; -- test if Id exists
 */
idsCookie = function(name, expires, path, domain, secure)
{
	this._name=name;
	this._expires=expires;
	this._path=path;
	this._domain=domain;
	this._secure=secure;
	  
    this._ids=new Array();
    this._idsFifo=new Array();
    this._minId=null;
    this.read();
}

idsCookie.prototype = new extCookie();

idsCookie.prototype._integer2ascii = new Array();
idsCookie.prototype._ascii2integer = new Array();

var n=0;
for(var i=0; i<10; i++)
{
	idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('0'.charCodeAt(0)+i);
}
for(var i=0; i<26; i++)
{
	idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('A'.charCodeAt(0)+i);
}
for(var i=0; i<26; i++)
{
	idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('a'.charCodeAt(0)+i);
}

idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('_'.charCodeAt(0));
idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('-'.charCodeAt(0));
idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('+'.charCodeAt(0));
idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('*'.charCodeAt(0));
idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('.'.charCodeAt(0));
idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('@'.charCodeAt(0));
//idsCookie.prototype._integer2ascii[n++]=String.fromCharCode('/'.charCodeAt(0));
// '/' is used as separator
for(var i=0; i<idsCookie.prototype._integer2ascii.length; i++)
{
	idsCookie.prototype._ascii2integer[idsCookie.prototype._integer2ascii[i]]=i;
}

idsCookie.prototype._compactInteger = function(n)
{
   var str='';
   while(n>=this._integer2ascii.length)
   {
       str=this._integer2ascii[n%this._integer2ascii.length]+str;
       n=Math.floor(n/this._integer2ascii.length);
   }
   str=this._integer2ascii[n]+str;
   return str;
}

idsCookie.prototype._uncompactInteger = function(str)
{
	var n=0;
	for(var i=str.length-1;i>=0;i--)
	{
		n+=this._ascii2integer[str.charAt(i)]*Math.pow(this._integer2ascii.length, str.length-i-1);
	}
	return n;
}

idsCookie.prototype.addId = function(id)
{
	if(this._minId===null||id<this._minId)this._minId=id;
	if(!this._ids[id])
	{
		this._ids[id]=true;
		this._idsFifo.unshift(id);
	}
}

idsCookie.prototype.isId = function(id)
{
	return (this._ids[id]===true);
}

idsCookie.prototype.write = function()
{
	this._value=this._compactInteger(this._minId)+'/';
	for(var i=0; i<this._idsFifo.length; i++)
	{
		if(this._ids[this._idsFifo[i]])
		{
			var str=this._compactInteger(this._idsFifo[i]-this._minId)+'/';
			if((this._value.length+str.length)>4000) break;
			this._value+=str;
		}
	}
	this.rawWrite();
}

idsCookie.prototype.read = function()
{
	this._ids=new Array();
    this._idsFifo=new Array();
    this._minId=null;
	
	this.rawRead();
	if(this._value)
	{
		var tmp=this._value.split('/');
		var min=this._uncompactInteger(tmp[0]);
		for(i=(tmp.length-2);i>0;i--)
		{
			this.addId(this._uncompactInteger(tmp[i])+min);
		}
	}
	return this._value;
}

/**
 * objCookie : cookie with fields
 * 
 * usage :
 * var myObjCookie = new objCookie('cookie2'); -- create/read the cookie
 * myObjCookie.setField('foo', 'bar'); -- add a new field
 * myObjCookie.write(); -- store the cookie
 * val = myObjCookie.getField('foo'); -- get the field value
 */
objCookie = function(name, expires, path, domain, secure)
{
	this._name=name;
	this._expires=expires;
	this._path=path;
	this._domain=domain;
	this._secure=secure;
	  
    this._fields=new Array();
    this.read();
}

objCookie.prototype = new extCookie();

objCookie.prototype.setField = function(name, value)
{
	this._fields[name]=value;
}

objCookie.prototype.getField = function(name, defaultValue)
{
	if(this._fields[name]===undefined) return defaultValue;
	if(this._fields[name]==='false') return false;
	if(this._fields[name]==='true') return true;
	return this._fields[name];
}

objCookie.prototype.write = function()
{
	this._value='';
	for(var field in this._fields)
	{
		this._value+='^'+field+':'+this._fields[field];
	}
	this.rawWrite();
}

objCookie.prototype.read = function()
{
	this._fields=new Array();	
	var re_fv = new RegExp('^\^([a-z][a-z0-9_]*)[:](.*)$','i');
	var match;
	
	this.rawRead();
	if(this._value)
	{
		var tmp=this._value.split('^');
		for(var i=0; i<tmp.length; i++)
		{
			if(match = re_fv.exec(tmp[i]))
			{
				this._fields[match[1]]=match[2];
			}			
		}
	}
	return this._value;
}